package ee.ut.maxorato_macobo.oop.mudclient.network;

import java.nio.charset.Charset;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class ClientFrameDecoder extends FrameDecoder {
	static ChannelBuffer ansiTag = ChannelBuffers.copiedBuffer("\033[", Charset.forName("US-ASCII"));
	static ChannelBuffer endTag = ChannelBuffers.copiedBuffer("m", Charset.forName("US-ASCII"));
	
	@Override
	protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception {
		ChannelBuffer frame = ChannelBuffers.dynamicBuffer();
		int toRead = -1;
		boolean hasOpeningTag = false;
		
		while((toRead = indexOf(buf, ansiTag)) >= 0) {
			frame.writeBytes(buf.readBytes(toRead));
			
			if((toRead = indexOf(buf, endTag)) < 0) {
				hasOpeningTag = true;
				break;
			}
			
			frame.writeBytes(buf.readBytes(toRead + endTag.capacity()));
		}
		
		if(!hasOpeningTag) {
			frame.writeBytes(buf.readBytes(buf.readableBytes()));
		}
		
		if(frame.readableBytes() > 0) return frame;
		else return null;
	}
	
	private static int indexOf(ChannelBuffer haystack, ChannelBuffer needle) {
		for (int i = haystack.readerIndex(); i < haystack.writerIndex(); i ++) {
			int haystackIndex = i, needleIndex;
			
			for (needleIndex = 0; needleIndex < needle.capacity(); needleIndex ++) {
				if (haystack.getByte(haystackIndex) != needle.getByte(needleIndex)) {
					break;
				} else {
					haystackIndex ++;
					if (haystackIndex == haystack.writerIndex() &&
						needleIndex != needle.capacity() - 1) {
						return -1;
					}
				}
			}
			if (needleIndex == needle.capacity()) {
				return i - haystack.readerIndex();
			}
		}
		
		return -1;
	}
}
